package cc.shacocloud.luanniao.core.service.oss

import cc.shacocloud.luanniao.core.config.OssProperties
import cc.shacocloud.luanniao.core.model.constant.StorageTypeEnum
import cc.shacocloud.luanniao.core.service.oss.local.LocalObjectStorageServiceImpl
import java.io.File
import java.io.FileInputStream
import java.io.IOException
import java.io.InputStream

/**
 * 对象存储服务接口
 */
interface ObjectStorageService {

    companion object {

        /**
         * 获取 oss 存储服务
         */
        fun getOss(properties: OssProperties): ObjectStorageService {
            return when (properties.type) {
                StorageTypeEnum.LOCAL -> LocalObjectStorageServiceImpl(requireNotNull(properties.local))
            }
        }

    }

    /**
     * 上传一个对象.
     *
     * @param bucket Bucket
     * @param objectKey    Key
     * @param file   上传对象的文件
     * @throws OSSException 如果文件上传异常则抛出该例外
     * @throws IOException  file 文件读取异常
     */
    @Throws(OSSException::class, IOException::class)
    fun putObject(
        bucket: String,
        objectKey: String,
        file: File,
    ) {
        FileInputStream(file).use { fileInputStream ->
            putObject(bucket, objectKey, fileInputStream, file.length())
        }
    }

    /**
     * 上传一个对象.
     *
     * @param bucket   Bucket
     * @param objectKey      Key
     * @param file     上传对象的文件
     * @param partSize 以 MultiPart 上传时的单个包大小（Bytes）
     * @throws IllegalArgumentException 如果  length，partSize参数不合法则抛出该异常
     * @throws OSSException             如果文件上传异常则抛出该例外
     * @throws IOException              file 文件读取异常
     */
    @Throws(IllegalArgumentException::class, OSSException::class, IOException::class)
    fun putObject(bucket: String, objectKey: String, file: File, partSize: Long?) {
        FileInputStream(file).use { fileInputStream ->
            putObject(bucket, objectKey, fileInputStream, file.length(), partSize)
        }
    }

    /**
     * 上传一个对象.
     *
     * @param bucket      Bucket
     * @param objectKey         Key
     * @param inputStream 上传对象的输入流，请自己关闭该流
     * @param length      上传对象的内容长度（Bytes）
     * @throws OSSException 如果文件上传异常则抛出该例外
     * @see .putObject
     */
    @Throws(IllegalArgumentException::class, OSSException::class)
    fun putObject(
        bucket: String,
        objectKey: String,
        inputStream: InputStream,
        length: Long,
        partSize: Long? = null,
    )

    /**
     * 判断指定对象是否存在.
     *
     * @param storeInfo 存储信息
     *
     * @return true：存在，false：不存在
     * @throws OSSException 文件读取异常
     */
    @Throws(OSSException::class)
    fun existObject(storeInfo: FileStoreInfo): Boolean {
        return existObject(storeInfo.bucket, storeInfo.objectKey)
    }

    /**
     * 判断指定对象是否存在.
     *
     * @param bucket Bucket
     * @param objectKey    Key
     * @return true：存在，false：不存在
     * @throws OSSException 文件读取异常
     */
    @Throws(OSSException::class)
    fun existObject(bucket: String, objectKey: String): Boolean

    /**
     * 获取指定对象的输入流
     *
     * @param storeInfo 存储信息
     * @return 对象的输入流
     * @throws ObjectNotFoundException 指定对象不存在
     * @throws OSSException            文件读取异常
     */
    @Throws(ObjectNotFoundException::class, OSSException::class)
    fun getObject(storeInfo: FileStoreInfo): InputStream {
        return getObject(storeInfo.bucket, storeInfo.objectKey)
    }

    /**
     * 获取指定对象的输入流
     *
     * @param bucket Bucket
     * @param objectKey    Key
     * @return 对象的输入流
     * @throws ObjectNotFoundException 指定对象不存在
     * @throws OSSException            文件读取异常
     */
    @Throws(ObjectNotFoundException::class, OSSException::class)
    fun getObject(bucket: String, objectKey: String): InputStream

    /**
     * 销毁该OSS对象，销毁后该对象的方法不在可以使用
     */
    fun destroy()
}
